#
最近试着用Swift基于AudioQueue写一个音乐播放器,但是AudioQueue的API都是C函数,避免不了操作指针。经常卡在指针上,于是决定先静下心来学习一下Swift中的指针。baidu了很多,但是没有系统讲解Swift指针的文章,一边学一边记录,写下这些作为积累。这次学习分为四个部分:UnsafePointer
, UnsafeMutablePointer
, UnsafeRawPointer
, UnsafeMutableRawPointer
。有不对的地方欢迎指出!
在Swift中,指针由结构体 struct UnsafePointer<Pointee>
或 struct UnsafeMutablePointer<Pointee>
表示,但是不能通过”&”获取一个UnsafePointer
或 UnsafeMutablePointer
的实例,只能作为inout
参数使用。UnsafePointer
相对于UnsafeMutablePointer
,其所指向的地址的值是不可变的
一、UnsafeMutablePointer
被UnsafeMutablePointe
引用的内存有三种状态:
\1. Not Allocated
\2. Allocated but not initialized
\3. Allocated and initialized
只有在状态3时,可以安全的使用pointee
属性来set
和get
。
1.初始化
allocate()
initialize()
deinitialize
deallocate()
这四个方法来管理这个指针,并确保指针的pointee
不会出错
(1) allocate
1 | let a_unsafe_mutable_pointer = UnsafeMutablePointer<Int>.allocate(capacity: 0)1 |
Tips:
\1. 需要指明要声明的指针类型
allocate
是静态方法
(2) initialize
1 | a_unsafe_mutable_pointer.initialize(to: 5) |
这两种方法的结果是相同的
(3) deinitialize
1 | a_unsafe_mutable_pointer.deinitialize(count: 1)1 |
该方法貌似没有真正deintialize,只是返回了一个指向相同地址的UnsafeMutableRawPointer
,并且a_unsafe_mutable_pointer.pointee
仍然是可以正常使用
(4) deallocate
1 | a_unsafe_mutable_pointer.deallocate(capacity: 1)1 |
此时a_unsafe_mutable_pointer不可用了。
2.互相转化
(1) UnsafeMutablePointer -> Swift
1 | let a : Int = a_unsafe_mutable_pointer.pointee1 |
(2) Swift -> UnsafeMutablePointer
1 | let a : UnsafeMutablePointer = &a 1 |
以上代码是错误的,只能作为函数参数使用,如下所示
1 | func printPointer(ptr:UnsafeMutablePointer<Int>) { |
3.暂时绑定
将该内存暂时绑定为一种类型,例子中将Int型绑定为Int8
1 | a_unsafe_mutable_pointer.initialize(to: 0x0102030A) |
二、UnsafePointer
UnsafePointer
中的pointee
属性只能get
不能set
。UnsafePointer
中没有allocate
方法。
1.初始化
1 | let a_unsafe_pointer = UnsafePointer<Int>.init(a_unsafe_mutable_pointer)1 |
可以由UnsafeMutablePointer
、OpaquePointer
或其他UnsafePointer
创建一个UnsafePointer
指针。其他与UnsafeMutablePointer
类似
2.互相转换
(1) UnsafeMutablePointer -> UnsafePointer
1 | let a_unsafe_pointer = UnsafePointer<Int>.init(a_unsafe_mutable_pointer)1 |
(2) UnsafePointer -> UnsafeMutablePointer
1 | let a_unsafe_mutable_pointer = UnsafePointer<Int>.init(mutating:a_unsafe_pointer)1 |
(3) UnsafePointer -> Swift
1 | let a : Int = a_unsafe_pointer.pointee1 |
(4) Swift -> UnsafePointer
与UnsafeMutablePointer
类似,只能作为函数参数引用
3.withUnsafePointer方法
withUnsafePointer
方法可以直接使用指针,但是不能改变pointee
的值
1 | var a = 0 |
三、UnsafeMutableRawPointer
UnsafeMutableRawPointer
按我的理解就是无类型的原始指针
1.分配内存
1 | var size = MemoryLayout<Int>.size |
这时,这个a_unsafe_mutable_raw_pointer
感觉没啥用,还是需要转换为UnsafeMutablePointer
来对内存进行操作。
2.初始化
初始化内存为Int类型,并赋值为1
1 | a_unsafe_mutable_raw_pointer.initializeMemory(as: Int.self, to: 1)1 |
3.绑定UnsafeMutablePointer
绑定了UnsafeMutablePointer
,使用UnsafeMutablePointer
才能对内存进行赋值,有两种方法绑定:
(1) bindMemory()
该方法绑定内存为指定类型并返回一个UnsafeMutablePointer<指定类型>
的指针
1 | var a_unsafe_mutable_pointer = a_unsafe_mutable_raw_pointer.bindMemory(to: Int.self, capacity: 1)1 |
(2) assumingMemoryBound()
该方法意思是直接转换这个原始指针为一个UnsafeMutablePointer<指定类型>
的指针
1 | var a_unsafe_mutable_pointer = a_unsafe_mutable_raw_pointer.assumingMemoryBound(to: Int.self)1 |
-
这样,就可以使用这个a_unsafe_mutable_pointer
进行其他操作了。
4.deallocate
最后,需要释放内存,首先要deinitialize,再deallocate
1 | a_unsafe_mutable_pointer.deinitialize() |
5.转换
(1) Swift -> UnsafeMutableRawPointer
1 | var a = 10 |
(2) UnsafeMutableRawPointer -> Swift
其过程应当为UnsafeMutableRawPointer
转换为UnsafeMutablePointer
,再由UnsafeMutablePointer
转换为Swift
指针
四、UnsafeRawPointer
UnsafeRawPointer
只能由其他指针用init
方法得到,与UnsafePointer
类似,没有allocate
静态方法。但是,与UnsafeMutableRawPointer
类似的有两种绑定方法,绑定成UnsafePointer
指针。